<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
		<link rel="Stylesheet" type="text/css" href="doc.css" />
		<title>Tutorial: EMF Model Transaction</title>
	</head>
	<body>
		<h1><a name="top">Tutorial: EMF Model Transaction</a></h1>

		<h2>Contents</h2>
		<ul>
			<li><a href="#overview">Overview</a></li>
			<li><a href="#refs">References</a></li>
			<li><a href="#intro">Introduction</a></li>
			<li><a href="#registrations">Registering an Editing Domain and a Listener</a></li>
			<li><a href="#obtainingEditingDomain">Obtaining the Editing Domain and Making Changes</a></li>
			<li><a href="#summary">Summary</a></li>
		</ul>

		<h2><a name="overview">Overview</a></h2>
		<p>
			The EMF transaction framework provides a means to manage multiple read/write threads on one
			EMF-style editing domain. Transactional editing domains can be registered with a unique identifier
			and later retrieved (or constructed). These editing domains conform to the standard EMF editing
			domain contract and can be used with little modification to client code to make it work in the context 
			of regular EMF-style commands.
		</p>
		<p>	
			Listeners receive events in batches and can be registered
			against particular editing domain(s) so that they are automatically added once the editing domain
			is constructed. When a transaction is finished and about to commit listeners can be given the
			opportunity to append more changes onto the end of the transaction. If a transaction is rolled back
			then listeners are not given the notification of the post-commit.
		</p>

		<p class="small">[<a href="#top">back to top</a>]</p>

		<h2><a name="refs">References</a></h2>
		<p>
			This tutorial assumes that the reader has knowledge of EMF and the eclipse PDE development
			environment. It is essential that the reader understands the basic reflective mechanisms of EMF 
			as well as its adapter/notifier system for broadcasting events.
		</p>
		<p class="small">[<a href="#top">back to top</a>]</p>

		<h2><a name="intro">Introduction</a></h2>
		<p>
			In order to demonstrate EMF Model Transaction, we will be making use of the library metamodel. This metamodel
			is a variant of the standard EMF example metamodel used in many of its tutorials.
		</p>
		<p>
			The goal of this tutorial is to create a single standard transactional editing domain with a single listener.
			Once that is done, code will be written to get (or construct) the editing domain so that changes
			are made on multiple threads (sequentially, not concurrently). These changes will be undone and redone
			automatically because the changes were done in a recording command.
		</p>
		<p class="small">[<a href="#top">back to top</a>]</p>
		
		<h2><a name="registrations">Registering an Editing Domain and a Listener</a></h2>
		<p>
			The following XML declares a new transactional editing domain and a new listener
			for that editing domain. Both operations can be done programmatically using the
			<code>TransactionalEditingDomain.Registry</code>, <code>TransactionalEditingDomain.Factory</code> and the 
			<code>TransactionalEditingDomain.addResourceSetListener()</code>.
		</p>
		
<pre class="codeblock">
   &lt;extension
         point=&quot;org.eclipse.emf.transaction.editingDomains&quot;&gt;
      &lt;editingDomain
            factory=&quot;transactionexample.MyEditingDomainFactory&quot;
            id=&quot;myExample&quot;/&gt;
   &lt;/extension&gt;
   &lt;extension
         point=&quot;org.eclipse.emf.transaction.listeners&quot;&gt;
      &lt;listener class=&quot;transactionexample.MyListener&quot;&gt;
      	&lt;editingDomain id=&quot;myExample&quot;/&gt;
      &lt;/listener&gt;
   &lt;/extension&gt;
</pre>
		<p>
			Here is the implementation of the editing domain factory:
		</p>
		
<pre class="codeblock">
	public class MyEditingDomainFactory
		implements Factory {
	
		public TransactionalEditingDomain createEditingDomain() {
			return TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain();
		}
	
		public TransactionalEditingDomain createEditingDomain(ResourceSet rset) {
			return TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(rset);
		}
	
		public TransactionalEditingDomain getEditingDomain(ResourceSet rset) {
			return TransactionalEditingDomain.Factory.INSTANCE.getEditingDomain(rset);
		}
	}
</pre>
	<p>
		The editing domain factory simply delegates to the singleton factory. If some
		 customizations were needed for the editing domain then the factory could handle
		 them here.	
	</p>

<pre class="codeblock">
public class MyListener
   extends ResourceSetListenerImpl {
   
   public void resourceSetChanged(ResourceSetChangeEvent event) {
      System.out.println("A change has been made with "+event.getNotifications().size()+" notifications produced.");
   }
   
   public Command transactionAboutToCommit(ResourceSetChangeEvent event)
      throws RollbackException {
      
      List notifications = event.getNotifications();
      CompoundCommand cc = new CompoundCommand();
      Set handledLibraries = new HashSet();
      
      for (Iterator i = notifications.iterator(); i.hasNext();) {
         Notification n = (Notification)i.next();
         
         if (n.getNotifier() instanceof EObject &amp;&amp; !handledLibraries.contains(n)) {
            EObject notifier = (EObject)n.getNotifier();
            if (notifier.eClass() == EXTLibraryPackage.eINSTANCE.getLibrary()) {
               final Library l = (Library)notifier;
               String name = l.getName();
               
               // Libraries should have some name
               if (name == null || name.equals("")) {
                  // We can use any EMF command here
                  cc.append(new SetCommand(event.getEditingDomain(),
                        l, EXTLibraryPackage.eINSTANCE.getLibrary_Name(), 
                        "SomeName"));
               }
               
               handledLibraries.add(l);
            }
         }
      }
      
      // It is important to return null if we have nothing to 
      //  contribute to this transaction.
      return cc.isEmpty() ? null : cc;
   }
}
</pre>	
		<p>
			The listener serves two purposes: automatically name Library objects if they have no name and 
			report to the console how many notifications were batched at the completion of each root transaction.
			It declares that it is interested in both the post commit and pre commit events by overriding
			the <code>isPrecommitOnly</code> and <code>isPostCommitOnly</code> methods.
			Note that the listener makes no attempt to modify the state of any EObjects
			as this would constitute a protocol violation. The listener makes an attempt to modify EObjects
			only as a command that it returns in the <code>transactionAboutToCommit</code>. At no point
			did the listener attempt to execute this command however. As an optimization,
			the listener ensures that it will return null for <code>transactionAboutToCommit</code> if
			it has nothing to add to the transaction.
		</p>
		<p>
			The listener could override the <code>getFilter</code> method in order to filter out any notifications
			that do not match the filter. For now, it will only filter out &quot;touch&quot; events.
		</p>
		
		<p class="small">[<a href="#top">back to top</a>]</p>

		<h2><a name="obtainingEditingDomain">Obtaining the Editing Domain and Making Changes</a></h2>
		<p>
			The editing domain, once registered is made available through the transactional editing domain
			registry singleton.
		</p>

<pre class="codeblock">
final TransactionalEditingDomain domain = 
		TransactionalEditingDomain.Registry.INSTANCE.getEditingDomain("myExample");
</pre>		

		<p>
			Once we have the editing domain we can begin working with it and editing it. We must make
			changes inside a command that is executed on the editing domain's command stack. The
			editing domain will ensure that the command is executed exclusively from any other
			commands being executed in other threads.
		</p>

<pre class="codeblock">
final Resource r = domain.getResourceSet().createResource(URI.createURI("file://foo.extlibrary"));

// We execute this command on the command stack because otherwise, we will not
//  have write permissions on the editing domain.
domain.getCommandStack().execute(new RecordingCommand(domain) {
	protected void doExecute() {
		Library l = EXTLibraryFactory.eINSTANCE.createLibrary();
		r.getContents().add(l);
		l.setName("");
	}
});
</pre>

		<p>
			We can have multiple threads attempting to access this editing domain. Each
			will be given exclusive access as long as we use the <code>runExclusive()</code>
			method on the editing domain.
		</p>

<pre class="codeblock">
Runnable getLibraryName = new Runnable() {
	public void run() {
		// Any reading that is done on the editing domain must be done inside an
		//  runExclusive call to ensure we have the read lock
		String libraryName = null;
		try {
			libraryName = (String)domain.runExclusive(new RunnableWithResult.Impl() {
				public void run() {
					// Find the library's name and pass it back to the caller.
					setResult(((Library)r.getContents().get(0)).getName());
				}
			});
		} catch (InterruptedException e) {
			// Handle the interrupted exception in an graceful way ...
		}
		
		// The library name won't be empty because our listener will
		//  give it a default name since we gave it an empty name.
		System.out.println(libraryName);
	}
};

Thread t1 = new Thread(getLibraryName);
Thread t2 = new Thread(getLibraryName);

t1.start();
t2.start();
</pre>

		<p class="small">[<a href="#top">back to top</a>]</p>

		<h2><a name="summary">Summary</a></h2>
		<p>
			In this tutorial, we did the following:
			<ol>
				<li>Declared a transactional editing domain with a unique identifier against
				    the extension point</li>
				<li>Registered a listener against that transactional editing domain using the
				    listeners extension point</li>
				<li>Made changes to the editing domain using a recording command that can undo/redo
				    itself automatically</li>
				<li>Read information from the editing domain exclusively using <code>RunnableWithResult</code>
				    so that we could more easily pass data back to the caller.</li>
			</ol>
		</p>
		<p class="small">[<a href="#top">back to top</a>]</p>

		<hr />

		<p>
			<a href="https://www.eclipse.org/legal/epl-2.0/">Copyright (c) 2006 IBM Corporation and others.</a>
		</p>
	</body>
</html>
